package cn.yunhe.java.security.provider;

import cn.yunhe.java.security.exception.VerifyCodeException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

@Component
public class MyAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    private UserDetailsService userDetailsService;

    //setter注入
    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    private PasswordEncoder passwordEncoder;

    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    public  MyAuthenticationProvider (UserDetailsService service,PasswordEncoder passwordEncoder) {
        this.setPasswordEncoder(passwordEncoder);
        this.setUserDetailsService(service);
        super.setHideUserNotFoundExceptions(false);
    }

    /**
     * 自定义认证过程
     * @param userDetails
     * @param authentication
     * @throws AuthenticationException
     */
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
          //1. 验证码校验
        MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails();
        String imageCode = details.getImageCode();
        String savedImageCode = details.getSavedImageCode();
        // 检验图形验证码
        if (StringUtils.isEmpty(imageCode) || StringUtils.isEmpty(savedImageCode) || !imageCode.equalsIgnoreCase(savedImageCode)) {
            //自定义异常
            throw new VerifyCodeException("验证码错误！");
        }

        //2.认证逻辑
       if(authentication.getCredentials()==null||"".equals(authentication.getCredentials())){
           throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials",
                   "密码不能为空!"));
        }else {
           String presentedPassword = authentication.getCredentials().toString();
           if (!new BCryptPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) {
               throw new BadCredentialsException(this.messages
                       .getMessage("AbstractUserDetailsAtuhenticationProvider.badCredentials",
                               "密码错误!"));
           }
       }
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        return userDetailsService.loadUserByUsername(username);
    }
}
